﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Controls;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitKernel.CurveUtility.LineGroupSuite;
using YJKRevitKernel.RevitTopologySuite;
using YJKGeometryFuncs;

namespace YJKRevitArea.AreaThumbnail
{
	public class DrawFirePreventionThumbnail
	{
		public DrawFirePreventionThumbnail(Autodesk.Revit.DB.Document doc)
		{
			this.m_doc = doc;
		}

		public void PrepareFilledRegionType()
		{
			List<FilledRegionType> list = (from n in new FilteredElementCollector(this.m_doc).OfClass(typeof(FilledRegionType))
			select n as FilledRegionType).ToList<FilledRegionType>();
			List<FillPatternElement> list2 = (from n in new FilteredElementCollector(this.m_doc).OfClass(typeof(FillPatternElement))
			where n.Name != "实体填充"
			select n as FillPatternElement).ToList<FillPatternElement>();
			if (list.Find((FilledRegionType e) => e.Name.Contains("防火分区面积填充")) == null)
			{
				try
				{
					int i = 4;
					FilledRegionType filledRegionType = list.First<FilledRegionType>();
					while (i > 0)
					{
						string text = string.Format("防火分区面积填充-{0}", i);
						FilledRegionType item = filledRegionType.Duplicate(text) as FilledRegionType;
						RevitVersionFuncs.SetFillPatternId(ref item, list2[i].Id);
						this.m_AreaFilledRegionType.Add(item);
						i--;
					}
					return;
				}
				catch (Exception ex)
				{
					this.m_AreaFilledRegionType.Clear();
					throw ex;
				}
			}
			this.m_AreaFilledRegionType = (from e in list
			where e.Name.Contains("防火分区面积填充")
			select e).ToList<FilledRegionType>();
		}

		public static List<List<Curve>> DeleteShortLine(List<List<Curve>> lstLstCv)
		{
			List<List<Curve>> list = new List<List<Curve>>();
			foreach (List<Curve> list2 in lstLstCv)
			{
				List<Curve> list3 = new List<Curve>();
				for (int i = 0; i < list2.Count; i++)
				{
					Curve curve = list2[i];
					if (YJKArchUtils.Utils.Geometry.LessThan(0.8, AssistFunc.feetToMM(curve.Length)))
					{
						if (list3.Count > 0)
						{
							Curve curve2 = list3[list3.Count - 1];
							if (!curve2.GetEndPoint(1).IsAlmostEqualTo(curve.GetEndPoint(0)))
							{
								DrawFirePreventionThumbnail.CreateCurveAgain(list3, curve, curve2);
							}
						}
						list3.Add(curve);
					}
				}
				Curve curve3 = list3[0];
				Curve curve4 = list3[list3.Count - 1];
				if (!curve4.GetEndPoint(1).IsAlmostEqualTo(curve3.GetEndPoint(0)))
				{
					DrawFirePreventionThumbnail.CreateCurveAgain(list3, curve3, curve4);
				}
				list.Add(list3);
			}
			return list;
		}

		private static void CreateCurveAgain(List<Curve> lstNewCv, Curve cv, Curve newCurve)
		{
			lstNewCv.Remove(newCurve);
			if (newCurve is Arc)
			{
				XYZ xyz = newCurve.Evaluate(0.5, true);
				lstNewCv.Add(Arc.Create(newCurve.GetEndPoint(0), cv.GetEndPoint(0), xyz));
				return;
			}
			lstNewCv.Add(Line.CreateBound(newCurve.GetEndPoint(0), cv.GetEndPoint(0)));
		}

		public bool DrawThumbnail(XYZ ptSelLocation, List<FirePreventionData> lstFirePreventionData, FirePreventionThumbnailData firePreventionThumbnailData)
		{
			this.PrepareFilledRegionType();
			List<List<Curve>> list = new List<List<Curve>>();
			List<ElementId> list2 = new List<ElementId>();
			int num = 0;
			bool flag = true;
			foreach (FirePreventionData firePreventionData in lstFirePreventionData)
			{
				List<ElementId> list3 = new List<ElementId>();
				new List<PointInfo>();
				List<List<Curve>> list4 = FirePreventionThumbnailManager.CreateTransform(firePreventionThumbnailData.ScalingRatio, firePreventionData.AreaOutline);
				list4 = DrawFirePreventionThumbnail.DeleteShortLine(list4);
				if (firePreventionData.AreaOutline.Count != 0)
				{
					list.AddRange(firePreventionData.AreaOutline);
					List<CurveInfo> list5 = new List<CurveInfo>();
					IList<Curve> list6 = list4[0];
					CurveLoop curveLoop = null;
					curveLoop = CurveLoop.Create(list6);
					if (curveLoop != null)
					{
						foreach (List<Curve> list7 in list4)
						{
							foreach (Curve cv in list7)
							{
								CurveInfo item = new CurveInfo(cv);
								list5.Add(item);
							}
						}
						if (firePreventionThumbnailData.IfSelectFill)
						{
							this.CreateFilledRegion(firePreventionThumbnailData, ref num, ref flag, list3, list4);
							list2.Add(this.m_doc.Create.NewGroup(list3).Id);
							list3.Clear();
						}
						RevitPolygonDataBean revitPolygonDataBean = new RevitPolygonDataBean(curveLoop, null, 3);
						XYZ ptWordLocation = null;
						if (revitPolygonDataBean.TryGetCenterPoint(out ptWordLocation))
						{
							this.CreateTextNode(firePreventionThumbnailData, firePreventionData, list3, ptWordLocation);
							list2.Add(this.m_doc.Create.NewGroup(list3).Id);
							list3.Clear();
						}
						list3.AddRange(this.DrawArea(list5, firePreventionThumbnailData.LineType));
						list2.Add(this.m_doc.Create.NewGroup(list3).Id);
					}
				}
			}
			if (firePreventionThumbnailData.IfSelectGird)
			{
				try
				{
					List<ElementId> collection = new List<ElementId>();
					this.DrawGrids(list, ref collection, firePreventionThumbnailData.ScalingRatio);
					list2.AddRange(collection);
				}
				catch
				{
				}
			}
			this.Move(list2, ptSelLocation);
			return true;
		}

		private void CreateTextNode(FirePreventionThumbnailData firePreventionThumbnailData, FirePreventionData firePreventionData, List<ElementId> lstArea, XYZ ptWordLocation)
		{
			double num = Convert.ToDouble(firePreventionThumbnailData.FirePreventionThumbnailSetUpData.CharacterHeight);
			double num2 = num * firePreventionThumbnailData.FirePreventionThumbnailSetUpData.RatioOfHeightToWidth;
			DrawFirePreventionThumbnail.ResetTextStyleSize(firePreventionThumbnailData.FirePreventionThumbnailSetUpData.TypefaceName, ref num, ref num2);
			double dLineWidth = this.GetStringLength(firePreventionData.GetAreaAllName()) * num2 / (double)this.m_doc.ActiveView.Scale;
			lstArea.Add(this.CreateAreaName(firePreventionData.GetAreaAllName(), ptWordLocation, firePreventionThumbnailData.FirePreventionThumbnailSetUpData.CharacterHeight, firePreventionThumbnailData.FirePreventionThumbnailSetUpData.RatioOfHeightToWidth, firePreventionThumbnailData.FirePreventionThumbnailSetUpData.TypefaceName, num / 3.0 * 2.0 * XYZ.BasisY, dLineWidth, false));
			dLineWidth = this.GetStringLength(firePreventionData.GetAreaName()) * num2 / (double)this.m_doc.ActiveView.Scale;
			lstArea.Add(this.CreateAreaName(firePreventionData.GetAreaName(), ptWordLocation, firePreventionThumbnailData.FirePreventionThumbnailSetUpData.CharacterHeight, firePreventionThumbnailData.FirePreventionThumbnailSetUpData.RatioOfHeightToWidth, firePreventionThumbnailData.FirePreventionThumbnailSetUpData.TypefaceName, -num / 3.0 * XYZ.BasisY, dLineWidth, false));
		}

		private void CreateFilledRegion(FirePreventionThumbnailData firePreventionThumbnailData, ref int nFilledRegionTypeNum, ref bool bSucc, List<ElementId> lstArea, List<List<Curve>> lstLstScalingCurve)
		{
			List<CurveLoop> list = new List<CurveLoop>();
			foreach (List<Curve> list2 in lstLstScalingCurve)
			{
				try
				{
					CurveLoop item = CurveLoop.Create(list2);
					list.Add(item);
				}
				catch
				{
				}
			}
			ElementId elementId = this.DrawFilledRegion(list, nFilledRegionTypeNum, firePreventionThumbnailData.LineType, ref bSucc);
			if (null != elementId)
			{
				lstArea.Add(elementId);
				nFilledRegionTypeNum++;
			}
		}

		private Curve GetCVZIsZero(Curve cv)
		{
			Curve result = null;
			if (cv is Line)
			{
				XYZ endPoint = cv.GetEndPoint(0);
				XYZ endPoint2 = cv.GetEndPoint(1);
				if (YJKArchUtils.Utils.Geometry.LessThan(endPoint.DistanceTo(endPoint2), AssistFunc.mmToFeet(0.8)))
				{
					return result;
				}
				XYZ xyz = new XYZ(endPoint.X, endPoint.Y, 0.0);
				XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, 0.0);
				result = Line.CreateBound(xyz, xyz2);
			}
			return result;
		}

		private void DrawGrids(List<List<Curve>> lstLstOutLine, ref List<ElementId> lsGroupIds, double dMultiple)
		{
			List<ILineGeter> list = new List<ILineGeter>();
			foreach (Element element in new FilteredElementCollector(this.m_doc).OfClass(typeof(Grid)))
			{
				Grid grid = element as Grid;
				if (grid != null)
				{
					FirePreventionUseLine firePreventionUseLine = new FirePreventionUseLine();
					if (grid.Curve is Line)
					{
						Curve cvzisZero = this.GetCVZIsZero(grid.Curve);
						if (null != cvzisZero)
						{
							firePreventionUseLine.UseLine = (cvzisZero as Line);
						}
						firePreventionUseLine.GridLine = true;
						firePreventionUseLine.Grid = grid;
						list.Add(firePreventionUseLine);
					}
				}
			}
			foreach (List<Curve> list2 in lstLstOutLine)
			{
				foreach (Curve curve in list2)
				{
					if (curve is Line)
					{
						FirePreventionUseLine firePreventionUseLine2 = new FirePreventionUseLine();
						Curve cvzisZero2 = this.GetCVZIsZero(curve);
						if (null != cvzisZero2)
						{
							firePreventionUseLine2.UseLine = (cvzisZero2 as Line);
						}
						firePreventionUseLine2.GridLine = false;
						list.Add(firePreventionUseLine2);
					}
				}
			}
			foreach (FirePreventionUseLine firePreventionUseLine3 in FirePreventionThumbnailManager.GetOldGridLocationLine(this.m_doc, list))
			{
				List<ElementId> list3 = new List<ElementId>();
				List<List<Curve>> list4 = FirePreventionThumbnailManager.CreateTransform(dMultiple, new List<List<Curve>>
				{
					new List<Curve>
					{
						firePreventionUseLine3.UseLine
					}
				});
				DetailCurve detailCurve = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, list4[0][0]);
				list3.Add(detailCurve.Id);
				Parameter parameter = firePreventionUseLine3.Grid.GetGridType().GetParameter("符号");
				if (parameter == null)
				{
					break;
				}
				ElementId elementId = parameter.AsElementId();
				parameter = this.m_doc.GetElement(elementId).GetParameter("半径");
				if (parameter == null)
				{
					break;
				}
				double num = (double)this.m_doc.ActiveView.Scale * parameter.AsDouble() * dMultiple;
				XYZ endPoint = list4[0][0].GetEndPoint(0);
				XYZ endPoint2 = list4[0][0].GetEndPoint(1);
				XYZ xyz = (list4[0][0] as Line).Direction * num;
				XYZ xyz2 = endPoint - xyz;
				Arc arc = Arc.Create(xyz2, xyz2.DistanceTo(endPoint), 0.0, Math.PI*2, XYZ.BasisX, XYZ.BasisY);
				DetailCurve detailCurve2 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, arc);
				list3.Add(detailCurve2.Id);
				XYZ xyz3 = endPoint2 + xyz;
				Arc arc2 = Arc.Create(xyz3, xyz3.DistanceTo(endPoint2), 0.0, Math.PI*2, XYZ.BasisX, XYZ.BasisY);
				DetailCurve detailCurve3 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, arc2);
				list3.Add(detailCurve3.Id);
				double num2 = 4.7 * dMultiple;
				double num3 = 0.3;
				double num4 = 0.02 * dMultiple;
				if (YJKArchUtils.Utils.Geometry.LessThan(num2, num3))
				{
					double num5 = num3 / num2;
					num4 *= num5;
					num2 = num3;
				}
				list3.Add(this.CreateAreaName(firePreventionUseLine3.GridName, endPoint + XYZ.BasisY * 1.5 * dMultiple, num2, 0.7, "仿宋", -xyz, num4, true));
				list3.Add(this.CreateAreaName(firePreventionUseLine3.GridName, endPoint2 + XYZ.BasisY * 1.5 * dMultiple, num2, 0.7, "仿宋", xyz, num4, true));
				lsGroupIds.Add(this.m_doc.Create.NewGroup(list3).Id);
			}
		}

		private double GetStringLength(string strInput)
		{
			if (string.IsNullOrEmpty(strInput))
			{
				return 0.0;
			}
			Encoding encoding = new ASCIIEncoding();
			double num = 0.0;
			byte[] bytes = encoding.GetBytes(strInput);
			for (int i = 0; i < bytes.Length; i++)
			{
				if (bytes[i] == 63)
				{
					num += 1.5;
				}
				else
				{
					num += 1.0;
				}
			}
			return num;
		}

		private static void ResetTextStyleSize(string strTextStyle, ref double dCharHeight, ref double dCharWidth)
		{
			if (strTextStyle.Contains("微软雅黑"))
			{
				dCharHeight *= 1.03;
				dCharWidth *= 0.7;
				return;
			}
			if (strTextStyle.Contains("长仿宋体"))
			{
				dCharHeight *= 0.8;
				dCharWidth *= 0.55;
				return;
			}
			if (strTextStyle.Contains("新宋体") || strTextStyle.Contains("宋体") || strTextStyle.Contains("仿宋") || strTextStyle.Contains("黑体"))
			{
				dCharHeight *= 0.85;
				dCharWidth *= 0.55;
				return;
			}
			dCharHeight *= 1.0;
			dCharWidth *= 0.8;
		}

		private List<ElementId> DrawArea(List<CurveInfo> lstCurveInfos, string strLinePattern)
		{
			List<ElementId> list = new List<ElementId>();
			GraphicsStyle graphicsStyle = this.GetGraphicsStyle(strLinePattern);
			if (graphicsStyle == null)
			{
				return list;
			}
			new OverrideGraphicSettings().SetProjectionLinePatternId(graphicsStyle.Id);
			try
			{
				foreach (CurveInfo curveInfo in lstCurveInfos)
				{
					Curve curve = curveInfo.Curve;
					try
					{
						XYZ xyz = new XYZ(curve.GetEndPoint(0).X, curve.GetEndPoint(0).Y, 0.0);
						XYZ xyz2 = new XYZ(curve.GetEndPoint(1).X, curve.GetEndPoint(1).Y, 0.0);
						DetailCurve detailCurve;
						if (curve is Line)
						{
							if (YJKGeometryFuncs.Geometry.LessThan(xyz.DistanceTo(xyz2), AssistFunc.mmToFeet(0.8)))
							{
								continue;
							}
							Line line = Line.CreateBound(xyz, xyz2);
							detailCurve = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line);
							detailCurve.LineStyle = graphicsStyle;
						}
						else
						{
							Arc oldarc = curve as Arc;
							Curve curve2 = null;
							FirePreventionThumbnailManager.CreateNewArc(oldarc, xyz2, xyz, ref curve2);
							detailCurve = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, curve2);
							detailCurve.LineStyle = graphicsStyle;
						}
						list.Add(detailCurve.Id);
					}
					catch (Exception ex)
					{
						YJKMessageBox.Show(ex.Message);
					}
				}
			}
			catch
			{
			}
			return list;
		}

		private GraphicsStyle GetGraphicsStyle(string strLinePattern)
		{
			IEnumerable<ElementId> validLineStyleIdsForFilledRegion = FilledRegion.GetValidLineStyleIdsForFilledRegion(this.m_doc);
			GraphicsStyle result = null;
			foreach (ElementId elementId in validLineStyleIdsForFilledRegion)
			{
				GraphicsStyle graphicsStyle = this.m_doc.GetElement(elementId) as GraphicsStyle;
				if (graphicsStyle.Name == strLinePattern)
				{
					result = graphicsStyle;
					break;
				}
			}
			return result;
		}

		private bool Move(List<ElementId> lstGroupIds, XYZ point)
		{
			Autodesk.Revit.DB.View activeView = this.m_doc.ActiveView;
			try
			{
				Group group = this.m_doc.Create.NewGroup(lstGroupIds);
				BoundingBoxXYZ boundingBoxXYZ = group.get_BoundingBox(activeView);
				XYZ xyz = new XYZ(boundingBoxXYZ.Min.X, boundingBoxXYZ.Max.Y, 0.0);
				ElementTransformUtils.MoveElement(this.m_doc, group.Id, point - xyz);
				group.UngroupMembers();
			}
			catch
			{
			}
			return true;
		}

		private ElementId CreateAreaName(string strName, XYZ ptLocation, double dCharacterHeight, double dRatioOfHeightToWidth, string strTypefaceName, XYZ ptOffset, double dLineWidth, bool bGridNum)
		{
			XYZ basisX = XYZ.BasisX;
			XYZ upDirection = this.m_doc.ActiveView.UpDirection;
			TextNoteType textNodeType = FirePreventionThumbnailManager.GetTextNodeType(this.m_doc, dCharacterHeight, dRatioOfHeightToWidth, strTypefaceName);
			TextNote textNode = this.m_doc.GetTextNode(this.m_doc.ActiveView, ptLocation + ptOffset, basisX, upDirection, dLineWidth, (Autodesk.Revit.DB.TextAlignFlags)128, strName, textNodeType);
			Parameter parameter = textNode.TextNoteType.GetParameter("背景");
			if (!bGridNum)
			{
				if (parameter != null)
				{
					parameter.Set(0);
				}
			}
			else if (parameter != null)
			{
				parameter.Set(1);
			}
			return textNode.Id;
		}

		private ElementId DrawFilledRegion(List<CurveLoop> lstCurveLoop, int nNum, string strLinePattern, ref bool bSucc)
		{
			if (lstCurveLoop.Count < 1)
			{
				return null;
			}
			FilledRegionType filledRegionType = null;
			if (this.m_AreaFilledRegionType.Count > nNum)
			{
				filledRegionType = this.m_AreaFilledRegionType[nNum];
			}
			else
			{
				filledRegionType = this.m_AreaFilledRegionType[nNum % this.m_AreaFilledRegionType.Count];
			}
			if (filledRegionType == null)
			{
				return null;
			}
			FilledRegion filledRegion = null;
			try
			{
				try
				{
					filledRegion = FilledRegion.Create(this.m_doc, filledRegionType.Id, this.m_doc.ActiveView.Id, lstCurveLoop);
				}
				catch
				{
					filledRegion = this.CreatrFilledRegionAgain(lstCurveLoop, filledRegionType);
				}
				if (filledRegion == null)
				{
					return null;
				}
				GraphicsStyle graphicsStyle = this.GetGraphicsStyle(strLinePattern);
				if (graphicsStyle != null)
				{
					filledRegion.SetLineStyleId(graphicsStyle.Id);
				}
			}
			catch
			{
				if (bSucc)
				{
					YJKMessageBox.Show("存在无法生成的填充区域");
					bSucc = false;
				}
				if (filledRegion == null)
				{
					return null;
				}
				this.m_doc.Delete(filledRegion.Id);
				return null;
			}
			return filledRegion.Id;
		}

		private FilledRegion CreatrFilledRegionAgain(List<CurveLoop> lstCurveLoop, FilledRegionType type)
		{
			List<List<Curve>> list = new List<List<Curve>>();
			foreach (CurveLoop collection in lstCurveLoop)
			{
				List<Curve> list2 = new List<Curve>();
				list2.AddRange(collection);
				list.Add(list2);
			}
			List<CurveLoop> list3 = new List<CurveLoop>();
			foreach (List<Curve> list4 in list)
			{
				List<Curve> list5 = new List<Curve>();
				new List<Curve>();
				for (int i = 0; i < list4.Count - 1; i++)
				{
					if (list5.Count == 0)
					{
						list5.Add(list4[i]);
					}
					else if (list5[list5.Count - 1].GetEndPoint(1).IsAlmostEqualTo(list4[i].GetEndPoint(0)))
					{
						list5.Add(list4[i]);
					}
					else
					{
						Curve curve = list5[list5.Count - 1].Clone();
						curve.MakeUnbound();
						Curve curve2 = list4[i].Clone();
						curve2.MakeUnbound();
						IntersectionResultArray intersectionResultArray = null;
						curve.Intersect(curve2, out intersectionResultArray);
						if (intersectionResultArray == null)
						{
							return null;
						}
						XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
						if (list5[list5.Count - 1] is Arc)
						{
							Arc arc = list4[list5.Count - 1] as Arc;
							Arc item = Arc.Create(arc.GetEndPoint(0), xyzpoint, arc.Evaluate(0.5, true));
							list5.RemoveAt(list5.Count - 1);
							list5.Add(item);
						}
						else
						{
							list5.RemoveAt(list5.Count - 1);
							list5.Add(Line.CreateBound(list4[0].GetEndPoint(0), xyzpoint));
						}
						if (list4[i] is Arc)
						{
							Arc arc2 = list4[i] as Arc;
							Arc item2 = Arc.Create(xyzpoint, arc2.GetEndPoint(1), arc2.Evaluate(0.5, true));
							list5.Add(item2);
						}
						else
						{
							list5.Add(Line.CreateBound(xyzpoint, list4[list4.Count - 1].GetEndPoint(1)));
						}
						i++;
					}
				}
				list5.Add(list4[list4.Count - 1]);
				if (!list4[0].GetEndPoint(0).IsAlmostEqualTo(list4[list4.Count - 1].GetEndPoint(1)))
				{
					Curve curve3 = list4[0].Clone();
					curve3.MakeUnbound();
					Curve curve4 = list4[list4.Count - 1].Clone();
					curve4.MakeUnbound();
					IntersectionResultArray intersectionResultArray2 = null;
					curve3.Intersect(curve4, out intersectionResultArray2);
					if (intersectionResultArray2 == null)
					{
						return null;
					}
					XYZ xyzpoint2 = intersectionResultArray2.get_Item(0).XYZPoint;
					if (list4[list4.Count - 1] is Arc)
					{
						Arc arc3 = list4[list4.Count - 1] as Arc;
						Arc item3 = Arc.Create(arc3.GetEndPoint(0), xyzpoint2, arc3.Evaluate(0.5, true));
						list5.Add(item3);
					}
					else
					{
						list5.Add(Line.CreateBound(list4[list4.Count - 1].GetEndPoint(0), xyzpoint2));
					}
					if (list4[0] is Arc)
					{
						Arc arc4 = list4[0] as Arc;
						Arc item4 = Arc.Create(xyzpoint2, arc4.GetEndPoint(1), arc4.Evaluate(0.5, true));
						list5.Add(item4);
					}
					else
					{
						list5.Add(Line.CreateBound(xyzpoint2, list4[0].GetEndPoint(1)));
					}
					list5.RemoveAt(0);
					list5.RemoveAt(list5.Count - 3);
				}
				CurveLoop item5 = null;
				try
				{
					item5 = CurveLoop.Create(list5);
				}
				catch
				{
					return null;
				}
				list3.Add(item5);
			}
			return FilledRegion.Create(this.m_doc, type.Id, this.m_doc.ActiveView.Id, list3);
		}

		private Document m_doc;

		private List<FilledRegionType> m_AreaFilledRegionType = new List<FilledRegionType>();
	}
}
